using System;
using System.Collections;
using Microsoft.SharePoint;
using System.Linq;

namespace SharePoint.DataMapper
{
	[FieldMapper(typeof(SPFieldLookup), SPFieldType.Lookup)]
	public class FieldLookupMapper : FieldMapper
	{
		protected override SPField AddFieldInternal(ListDataContext context, SPFieldCollection collection, Type propertyType, FieldAttribute attribute)
		{
			Guid listId;
			if (string.IsNullOrEmpty(attribute.LookupList))
			{
				Type itemType = propertyType.IsGenericType ? propertyType.GetGenericArguments()[0] : propertyType;
				IListData listBase = context.GetList(itemType);
				listId = listBase.Id;
			}
			else
			{
				listId = context.Web.GetListGuid(attribute.LookupList);
			}
			string name = collection.AddLookup(attribute.Field, listId, attribute.Required);
			SPFieldLookup field = (SPFieldLookup)collection.GetFieldByInternalName(name);
			SetFieldPropertiesInternal(field, attribute);
			field.AllowMultipleValues = attribute.AllowMultipleValues;
			return field;
		}

		protected override FieldAttribute GetFieldAttributeInternal(SPField field)
		{
			FieldAttribute attribute = base.GetFieldAttributeInternal(field);
			SPFieldLookup fieldLookup = field as SPFieldLookup;
			if (fieldLookup == null)
			{
				return attribute;
			}
			attribute.AllowMultipleValues = fieldLookup.AllowMultipleValues;
			attribute.LookupList = fieldLookup.LookupList;
			return attribute;
		}

		protected override object SetFieldInternal(ListDataContext context, object value, Type propertyType)
		{
			if (value is SPFieldLookupValueCollection)
			{
				return value;
			}
			if (value is SPFieldLookupValue)
			{
				return value;
			}
			if (value is IItemBase)
			{
				return ((IItemBase)value).Id;
			}
			if (value is IList)
			{
				SPFieldLookupValueCollection values = new SPFieldLookupValueCollection();
				IList list = (IList)value;
				foreach (object v in list)
				{
					if (v is IItemBase)
					{
						IItemBase itemBase = (IItemBase)v;
						values.Add(new SPFieldLookupValue(itemBase.Id, itemBase.Title));
					}
				}
				return values.ToString();
			}
			return null;
			
		}

		protected override object GetFieldInternal(ListDataContext context, object value, Type propertyType)
		{
			SPFieldLookupValueCollection lookupValues = (value is SPFieldLookupValueCollection) ? (SPFieldLookupValueCollection)value : new SPFieldLookupValueCollection(value.ToString());
			if (typeof(SPFieldLookupValueCollection) == propertyType)
			{
				return lookupValues;
			}
			if (typeof(SPFieldLookupValue) == propertyType)
			{
				return lookupValues.FirstOrDefault();
			}
			if (typeof(IItemBase).IsAssignableFrom(propertyType))
			{
				SPFieldLookupValue lookupValue = lookupValues.FirstOrDefault();
				if (lookupValue != null)
				{
					IListData listBase = context.GetList(propertyType);
					return listBase.GetItem(lookupValue.LookupId);
				}
			}
			if (typeof(IList).IsAssignableFrom(propertyType) && propertyType.IsGenericType)
			{
				Type itemType = propertyType.GetGenericArguments()[0];
				IList list = (IList)Activator.CreateInstance(propertyType);

				IListData listBase = context.GetList(itemType);
				foreach (SPFieldLookupValue lookupValue in lookupValues)
				{
					value = listBase.GetItem(lookupValue.LookupId);
					list.Add(value);
				}
				return list;
			}
			return null;
		}
	}
}